"use client";
import React, {
  MouseEvent,
  MutableRefObject,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from "react";
import {
  Stage,
  Layer,
  // Rect,
  Image as KnovaImage,
  Shape,
} from "react-konva";
import Konva from "konva";
import { isDrawLineMode, useDrawLine } from "./useDrawLine";
import { useHistoryRecords } from "./useHistoryRecords";
import {
  DrawLineData,
  EditorMode,
  HistoryAction,
  HistoryRecord,
  ImageEditorRef,
  IPosition,
  MaskImgData,
} from "./type";
import {
  createTransparentGridPattern,
  getImageData,
  hexToRgb,
  isSameColor,
  isWhite,
  trimTransparent,
} from "./utils";
import { useFrameSelection } from "./useFrameSelection";
import { useImageRender } from "./useImageRender";
import { useDragble } from "./useDragble";
import { Context } from "konva/lib/Context";

// 一定要禁用，不然会给你不同的宽高尺寸
Konva.pixelRatio = 1;

interface ImageEditorProps {
  mode: EditorMode;
  scale: number;
  setScale: (scale: number) => void;
  classname?: string;
  /**要处理的图片地址 */
  imgUrl: string;
  /**蒙层初始化图片 */
  maskImgUrl?: string;
  /**蒙层颜色 */
  maskColor?: string;
  /**蒙层透明度 */
  maskOpacity?: number;
  /**反转蒙层 */
  reverse?: boolean;
  /**涂抹/橡皮擦 的线宽 */
  drawLineWidth?: number;
  /**框选回调 */
  onFrameSelected?: (start: IPosition, end: IPosition) => void;
  editorRef: MutableRefObject<ImageEditorRef | null>;
}
const ImageEditor = (props: ImageEditorProps) => {
  const {
    mode,
    scale,
    setScale,
    imgUrl,
    maskImgUrl,
    maskColor = "#df4b26",
    maskOpacity = 0.5,
    drawLineWidth = 10,
    reverse,
    onFrameSelected,
    editorRef,
  } = props;

  const historyMng = useHistoryRecords();

  // 添加位置状态
  const drag = useDragble();

  const { img, imageSize, containerRef } = useImageRender(imgUrl, setScale);
  //
  const drawLine = useDrawLine(mode, historyMng, scale, drawLineWidth);

  const frameSelection = useFrameSelection({
    onSelected: onFrameSelected,
    showBorderAfterDrag: false,
  });

  const onMouseDown = useCallback(
    (e: MouseEvent<HTMLDivElement>) => {
      switch (mode) {
        case EditorMode.DrawLine:
          drawLine.handleMouseDown(e);
          break;
        case EditorMode.Erase:
          drawLine.handleMouseDown(e);
          break;
        case EditorMode.FrameSelect:
          frameSelection.onMouseDown(e);
          break;
        case EditorMode.View:
          drag.handleDragStart(e);
          break;
        default:
          break;
      }
    },
    [drag, drawLine, frameSelection, mode]
  );

  const onMouseMove = useCallback(
    (e: MouseEvent<HTMLDivElement>) => {
      switch (mode) {
        case EditorMode.DrawLine:
        case EditorMode.Erase:
          drawLine.handleMouseMove(e);
          break;
        case EditorMode.FrameSelect:
        // frameSelection.onMouseMove(e);
        default:
          return;
      }
    },
    [drawLine, mode]
  );

  const onMouseUp = useCallback(
    () => {
      switch (mode) {
        case EditorMode.DrawLine:
        case EditorMode.Erase:
          drawLine.handleMouseUp();
          break;
        case EditorMode.FrameSelect:
        // frameSelection.onMouseUp(e);
        default:
          return;
      }
    },
    [drawLine, mode] // 添加 frameSelection 到依赖数组
  );

  const onMouseLeave = useCallback(
    (e: MouseEvent<HTMLDivElement>) => {
      switch (mode) {
        case EditorMode.DrawLine:
          drawLine.handleMouseLeave(e);
          break;
        case EditorMode.Erase:
          drawLine.handleMouseLeave(e);
          break;
        case EditorMode.FrameSelect:
          // frameSelection.onMouseLeave(e);
          break;
      }
    },
    [drawLine, mode]
  );

  const renderImageSize = useMemo(() => {
    return {
      width: imageSize.width * scale,
      height: imageSize.height * scale,
    };
  }, [imageSize, scale]);

  const addMaskImageUrl = useCallback(
    async function addMaskImageUrl(url: string) {
      const data = await getImageData(url);
      historyMng.push({
        action: HistoryAction.AddMaskImage,
        data: {
          url,
          image: data.img,
        },
      });
    },
    [historyMng]
  );

  useEffect(() => {
    if (maskImgUrl) {
      addMaskImageUrl(maskImgUrl);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const renderLine = useCallback(
    (ctx: CanvasRenderingContext2D, data: DrawLineData, scale: number) => {
      ctx.lineCap = "round";
      ctx.lineJoin = "round";
      ctx.strokeStyle = maskColor;

      if (data.mode === EditorMode.Erase) {
        ctx.globalCompositeOperation = "destination-out";
      } else {
        ctx.globalCompositeOperation = "source-over";
      }

      if (data.points.length < 2) {
        return;
      }

      ctx.lineWidth = data.strokeWidth * scale;
      ctx.beginPath();
      ctx.moveTo(data.points[0] * scale, data.points[1] * scale);
      for (let i = 2; i < data.points.length; i += 2) {
        ctx.lineTo(data.points[i] * scale, data.points[i + 1] * scale);
      }
      ctx.stroke();
    },
    [maskColor]
  );

  const renderMask = useCallback(
    (records: HistoryRecord[]) => {
      // console.time("renderMask");
      const size = imageSize;
      const scale = size.width < 500 ? 1 : 500 / size.width;
      const canva = document.createElement("canvas");
      canva.width = size.width * scale;
      canva.height = size.height * scale;

      const ctx = canva.getContext("2d", { willReadFrequently: true });

      if (!ctx) return null;

      for (let i = 0; i < records.length; i++) {
        const item = records[i];
        let data = item.data;
        switch (item.action) {
          case HistoryAction.DrawLine:
            data = data as DrawLineData;
            renderLine(ctx, data, scale);
            break;
          case HistoryAction.AddMaskImage:
            data = data as MaskImgData;
            ctx.globalCompositeOperation = "destination-over";
            ctx.drawImage(data.image, 0, 0, canva.width, canva.height);
            break;
          default:
            break;
        }
      }

      // console.timeLog("renderMask", "draw");

      if (drawLine.currentLine) {
        renderLine(ctx, drawLine.currentLine, scale);
      }

      const maskColorRgba = hexToRgb(maskColor as string);
      if (!maskColorRgba) {
        return null;
      }

      const imageData = ctx.getImageData(0, 0, canva.width, canva.height);
      const data = imageData.data;

      for (let i = 3; i < data.length; i += 4) {
        if (
          isWhite(data[i - 3], data[i - 2], data[i - 1]) ||
          isSameColor([data[i - 3], data[i - 2], data[i - 1]], maskColorRgba)
        ) {
          data[i - 3] = maskColorRgba[0];
          data[i - 2] = maskColorRgba[1];
          data[i - 1] = maskColorRgba[2];
          data[i] = 255 * maskOpacity;
        } else {
          data[i - 3] = 0;
          data[i - 2] = 0;
          data[i - 1] = 0;
          data[i] = 0;
        }
      }

      ctx.putImageData(imageData, 0, 0);

      // console.timeEnd("renderMask");
      return canva;
    },
    [imageSize, maskColor, maskOpacity, drawLine.currentLine, renderLine]
  );

  const [maskCanva, setMaskCanva] = useState<HTMLCanvasElement | null>(null);
  const [processedCanva, setProcessedCanva] =
    useState<HTMLCanvasElement | null>(null);

  const renderProcessedImage = useCallback(
    function (img: HTMLImageElement, maskCanva: HTMLCanvasElement | null) {
      const size = imageSize;
      const scale = size.width < 500 ? 1 : 500 / size.width;
      const canva = document.createElement("canvas");
      canva.width = size.width * scale;
      canva.height = size.height * scale;

      const ctx = canva.getContext("2d", { willReadFrequently: true });

      if (!ctx || !maskCanva) return null;

      ctx.drawImage(img, 0, 0, canva.width, canva.height);

      const imageData = ctx.getImageData(0, 0, canva.width, canva.height);

      const maskCtx = maskCanva.getContext("2d", { willReadFrequently: true });  
      const maskData = maskCtx?.getImageData(0, 0, canva.width, canva.height);

      // 抠图
      if (imageData && maskData) {
        // 遍历所有像素，修改 Alpha 通道
        for (let i = 3; i < imageData.data.length; i += 4) {
          const isMask = reverse ? !maskData.data[i - 1] : maskData.data[i - 1];

          if (isMask) continue; // 透明的部分跳过(即不绘制)
          // 设置透明度
          imageData.data[i] = 0; // Alpha 范围 0~255
        }
        ctx.putImageData(imageData, 0, 0);
      }

      return canva;
    },
    [imageSize, reverse]
  );

  // 渲染mask 和 处理后的图片
  useEffect(() => {
    if (historyMng.records.length === 0 || !renderImageSize.width || !img) {
      return;
    }
    const maskCanva = renderMask(historyMng.records);
    const processCanva = renderProcessedImage(img, maskCanva);
    setMaskCanva(maskCanva);
    setProcessedCanva(processCanva);
  }, [
    img,
    historyMng.records,
    renderImageSize,
    drawLine.currentLine,
    renderMask,
    renderProcessedImage,
  ]);

  useEffect(() => {
    if (editorRef) {
      editorRef.current = {
        async getMaskImage() {
          return maskCanva?.toDataURL("image/png");
        },
        async getProcessedImage() {
          // 生成处理后的图片，按照原图尺寸
          return {
            img: processedCanva?.toDataURL("image/png"),
            trimImg: trimTransparent(processedCanva)?.toDataURL("image/png"),
          };
        },
        addMaskImageUrl,
        clearHistory: historyMng.clear,
        undo: historyMng.undo,
        redo: historyMng.redo,
        setScale,
      };
    }
  }, [
    addMaskImageUrl,
    editorRef,
    historyMng,
    img,
    maskCanva,
    processedCanva,
    renderMask,
    renderProcessedImage,
    setScale,
  ]);

  return (
    <div
      className='flex items-stretch w-full h-full overflow-hidden'
      ref={containerRef}
    >
      {img && imageSize.width > 0 && imageSize.height > 0 && (
        <>
          <div className='bg-gray-300 p-3 w-1/2 max-w-1/2 flex justify-center items-center overflow-hidden relative'>
            <div
              className='relative'
              style={{
                width: renderImageSize.width,
                height: renderImageSize.height,
                cursor: mode === EditorMode.View ? "move" : "default",
                ...drag.style,
              }}
              onMouseDown={onMouseDown}
              onMouseMove={onMouseMove}
              onMouseUp={onMouseUp}
              onMouseLeave={onMouseLeave}
            >
              {isDrawLineMode(mode) && drawLine.brushCursor}
              {frameSelection.SelectionBorder}
              <Stage
                width={renderImageSize.width}
                height={renderImageSize.height}
              >
                <Layer>
                  <KnovaImage
                    image={img}
                    x={0}
                    y={0}
                    width={renderImageSize.width}
                    height={renderImageSize.height}
                  />
                </Layer>
                {/* Mask */}
                <Layer>
                  {maskCanva && (
                    <KnovaImage
                      image={maskCanva}
                      x={0}
                      y={0}
                      width={renderImageSize.width}
                      height={renderImageSize.height}
                    />
                  )}
                </Layer>
              </Stage>
            </div>
          </div>
          {/* 右侧抠图部分 */}
          <div className='bg-gray-300 p-3 w-1/2 max-w-1/2 flex justify-center items-center overflow-hidden relative'>
            <div
              className='relative'
              style={{
                width: renderImageSize.width,
                height: renderImageSize.height,
                cursor: mode === EditorMode.View ? "move" : "default",
                ...drag.style,
              }}
              onMouseDown={(e) => {
                if (mode !== EditorMode.View) return;
                drag.handleDragStart(e);
              }}
            >
              {frameSelection.SelectionBorder}
              {isDrawLineMode(mode) && drawLine.brushCursor}
              <Stage
                width={renderImageSize.width}
                height={renderImageSize.height}
              >
                <Layer>
                  <Shape
                    sceneFunc={(ctx) => {
                      // 绘制网格背景，实现透明背景
                      createTransparentGridPattern(
                        ctx as unknown as CanvasRenderingContext2D,
                        renderImageSize
                      );
                    }}
                  ></Shape>
                </Layer>
                <Layer>
                  {processedCanva && (
                    <KnovaImage
                      image={processedCanva}
                      x={0}
                      y={0}
                      width={renderImageSize.width}
                      height={renderImageSize.height}
                    />
                  )}
                </Layer>
              </Stage>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

export default ImageEditor;
